home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 10 / AACD 10.iso / AACD / Online / SpeakFreely / src / rate.c < prev    next >
C/C++ Source or Header  |  2000-05-18  |  4KB  |  168 lines

  1.  
  2. /*
  3.  * July 5, 1991
  4.  * Copyright 1991 Lance Norskog And Sundry Contributors
  5.  * This source code is freely redistributable and may be used for
  6.  * any purpose.  This copyright notice must be maintained. 
  7.  * Lance Norskog And Sundry Contributors are not responsible for 
  8.  * the consequences of using this software.
  9.  */
  10.  
  11. /*
  12.  
  13.  * Modified for use in Speak Freely by John Walker
  14.  
  15.  * Sound Tools rate change effect file.
  16.  */
  17.  
  18. #include "speakfree.h"
  19.  
  20. /*
  21.  * Least Common Multiple Linear Interpolation 
  22.  *
  23.  * Find least common multiple of the two sample rates.
  24.  * Construct the signal at the LCM by interpolating successive
  25.  * input samples as straight lines.  Pull output samples from
  26.  * this line at output rate.
  27.  *
  28.  * Of course, actually calculate only the output samples.
  29.  *
  30.  * LCM must be 32 bits or less.  Two prime number sample rates
  31.  * between 32768 and 65535 will yield a 32-bit LCM, so this is 
  32.  * stretching it.
  33.  */
  34.  
  35. /*
  36.  * Algorithm:
  37.  *  
  38.  *  Generate a master sample clock from the LCM of the two rates.
  39.  *  Interpolate linearly along it.  Count up input and output skips.
  40.  *
  41.  *  Input:   |inskip |         |         |         |         |
  42.  *                                    
  43.  *                                    
  44.  *                                    
  45.  *  LCM:     |     |   |     |   |     |   |     |   |     |   |
  46.  *                                    
  47.  *                                    
  48.  *                                    
  49.  *  Output:  |    outskip  |         |         | 
  50.  *
  51.  *                                    
  52.  */
  53.  
  54. typedef unsigned int u_i;
  55. typedef unsigned long u_l;
  56. typedef unsigned short u_s;
  57.  
  58. /* Private data for Lerp via LCM file */
  59. typedef struct ratestuff {
  60.     u_l    lcmrate;        /* least common multiple of rates */
  61.     u_l    inskip, outskip;    /* LCM increments for I & O rates */
  62.     u_l    total;
  63.     u_l    intot, outtot;        /* total samples in terms of LCM rate */
  64.     long    lastsamp;
  65. } rate_t;
  66.  
  67. static rate_t rt;
  68. static rate_t *rate = &rt;
  69.  
  70. /* here for linear interp.  might be useful for other things */
  71.  
  72. static long gcd(a, b) 
  73. long a, b;
  74. {
  75.     if (b == 0)
  76.         return a;
  77.     else
  78.         return gcd(b, a % b);
  79. }
  80.  
  81. static long lcm(a, b) 
  82. long a, b;
  83. {
  84.     return (a * b) / gcd(a, b);
  85. }
  86.  
  87. /*
  88.  * Prepare processing.
  89.  */
  90. void rate_start(inrate, outrate)
  91.   int inrate, outrate;
  92. {
  93.     rate->lcmrate = lcm((long) inrate, (long) outrate);
  94.     /* Cursory check for LCM overflow.  
  95.      * If both rate are below 65k, there should be no problem.
  96.      * 16 bits x 16 bits = 32 bits, which we can handle.
  97.      */
  98.     rate->inskip = rate->lcmrate / inrate;
  99.     rate->outskip = rate->lcmrate / outrate; 
  100.     rate->total = rate->intot = rate->outtot = 0;
  101.     rate->lastsamp = 0;
  102. }
  103.  
  104. /*
  105.  * Processed signed long samples from ibuf to obuf.
  106.  * Return number of samples processed.
  107.  */
  108.  
  109. void rate_flow(ibuf, obuf, isamp, osamp)
  110. unsigned char *ibuf, *obuf;
  111. int *isamp, *osamp;
  112. {
  113.     int len, done;
  114.     int skip;
  115.     unsigned char *istart = ibuf;
  116.     long last;
  117.     
  118.     done = 0;
  119.  
  120.     if (rate->total == 0) {
  121.         /* Emit first sample.  We know the fence posts meet. */
  122.         *obuf = *ibuf++;
  123.         /* Count up until have right input samples */
  124.         rate->lastsamp = audio_u2s(*obuf++);
  125.         done = 1;
  126.         rate->total = 1;
  127.         /* advance to second output */
  128.         rate->outtot += rate->outskip;
  129.         /* advance input range to span next output */
  130.         while ((rate->intot + rate->inskip) <= rate->outtot){
  131. /*            last = audio_u2s(*ibuf++); */
  132.             ibuf++;
  133.             rate->intot += rate->inskip;
  134.         }
  135.     }
  136.  
  137.     /* number of output samples the input can feed */
  138.  
  139.     len = (*isamp * rate->inskip) / rate->outskip;
  140.     if (len > *osamp)
  141.         len = *osamp;
  142.     last = rate->lastsamp;
  143.     for(; done < len; done++) {
  144.         int osl;
  145.  
  146. /*        osl = last;*/
  147.         osl = last + ((long) (audio_u2s(*ibuf) - last) *
  148.             ((long) rate->outtot - rate->intot)) / rate->inskip;
  149.         *obuf++ = audio_s2u(osl);
  150.         /* advance to next output */
  151.         rate->outtot += rate->outskip;
  152.         /* advance input range to span next output */
  153.         while ((rate->intot + rate->inskip) <= rate->outtot){
  154.             last = audio_u2s(*ibuf++);
  155.             rate->intot += rate->inskip;
  156.             if (ibuf - istart == *isamp)
  157.                 goto out;
  158.         }
  159.                 /* long samples with high LCM's overrun counters! */
  160.         if (rate->outtot == rate->intot)
  161.             rate->outtot = rate->intot = 0;
  162.     }
  163. out:
  164.     *isamp = ibuf - istart;
  165.     *osamp = len;
  166.     rate->lastsamp = last;
  167. }
  168.